package com.alibaba.cloud.ai.example.prompt.controller;

import com.alibaba.cloud.ai.dashscope.chat.DashScopeChatOptions;
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.ai.chat.client.advisor.MessageChatMemoryAdvisor;
import org.springframework.ai.chat.client.advisor.SimpleLoggerAdvisor;
import org.springframework.ai.chat.memory.InMemoryChatMemory;
import org.springframework.ai.chat.model.ChatModel;
import org.springframework.ai.chat.model.ChatResponse;
import org.springframework.ai.chat.prompt.Prompt;
import org.springframework.http.MediaType;
import org.springframework.http.codec.ServerSentEvent;
import org.springframework.web.bind.annotation.*;
import reactor.core.publisher.Flux;

@RestController
@CrossOrigin("*")
public class ChatController {

    private final ChatClient chatClient;

    private static final String DEFAULT_PROMPT = "你是一个学识渊博的人，乐意指导别人。";

    private final ChatModel chatModel;

    /**
     * 1.使用的 Spring Boot 自动装配默认生成的 ChatClient.Builder 的 bean，把它注入到您自己的类中
     * 2.可以通过设置属性 spring.ai.chat.client.enabled=false 来禁用 ChatClient.Builder bean 的自动配置，如果需要多个聊天模型一起使用，这会很有用，然后以编程方式创建 ChatClient.Builder，这样可以为每个聊天模型创建一个实例 ChatModel：
     */
    public ChatController(ChatClient.Builder chatClientBuilder,
                          ChatModel chatModel) {
        this.chatModel = chatModel;
        // 构造时，可以设置 ChatClient 的参数
        // {@link org.springframework.ai.chat.client.ChatClient};
        this.chatClient = ChatClient.builder(chatModel)
                .defaultSystem(DEFAULT_PROMPT)
                // 实现 Chat Memory 的 Advisor
                // 在使用 Chat Memory 时，需要指定对话 ID，以便 Spring AI 处理上下文。
                .defaultAdvisors(
                        new MessageChatMemoryAdvisor(new InMemoryChatMemory())
                )
                // 实现 Logger 的 Advisor
                .defaultAdvisors(
//                        new SimpleLoggerAdvisor()
                        new SimpleLoggerAdvisor(
                                request -> "Custom request: " + request.userText(),
                                response -> "Custom response: " + response.getResult(),
                                0
                        )
                )
                // 设置 ChatClient 中 ChatModel 的 Options 参数
                .defaultOptions(
                        DashScopeChatOptions.builder()
                                .withTopP(0.7)
                                .build()
                )
                .build();
    }

    @GetMapping("/chat")
    String generation(@RequestParam(value = "topic", defaultValue = "讲一个笑话") String userInput) {
        return this.chatClient.prompt()
                .user(userInput)
                .call()
                .content();
    }

    @GetMapping("/chat2")
    String generation2(@RequestParam(value = "topic", defaultValue = "讲一个幽默") String userInput) {
        ChatResponse response = chatModel.call(new Prompt(userInput));
        return response.getResult().getOutput().getContent();
    }

    @PostMapping(value = "/chat/stream", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
    public Flux<ServerSentEvent<String>> streamChat(@RequestBody ChatRequest request) {
        //用户id
        String userId = request.userId();

        return chatClient.prompt(request.message())
                .functions("gaoDeGetAddressWeatherFunction")
                .stream().content().map(content -> ServerSentEvent.builder(content).event("message").build())
                //问题回答结速标识,以便前端消息展示处理
                .concatWithValues(ServerSentEvent.builder("[DONE]").build())
                .onErrorResume(e -> Flux.just(ServerSentEvent.builder("Error: " + e.getMessage()).event("error").build()));

    }

    record ChatRequest(String userId, String message) {

    }
}
